package cn.wit.summit.chwan.net;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import cn.wit.summit.chwan.R;
import cn.wit.summit.chwan.models.db.NetResultCacheTable;
import cn.wit.summit.chwan.models.dbmanager.NetResultCacheManager;
import cn.wit.summit.chwan.models.dto.ParmsBean;
import cn.wit.summit.chwan.models.event.NotNetEvent;
import cn.wit.summit.chwan.models.response.ResponseBase;
import cn.wit.summit.chwan.net.okhttplib.HttpInfo;
import cn.wit.summit.chwan.net.okhttplib.callback.Callback;
import cn.wit.summit.chwan.ui.base.BaseActivity;
import cn.wit.summit.chwan.ui.base.MyActivity;
import cn.wit.summit.chwan.utils.LogUtils;
import cn.wit.summit.chwan.utils.StringUtils;

/**
 * Created by Alan on 2018/3/8.
 */

public class NetCallBack<T> implements Callback {

    private Gson mGson;
    private Context context;
    private Back<T> mBack;
    private Class beanClass;
    private boolean isShow = false;

    public NetCallBack(Context context, Class beanClass, Back<T> mBack) {
        this.context = context;
        this.beanClass = beanClass;
        this.mBack = mBack;
        mGson = new Gson();
    }

    public NetCallBack(Context context, boolean isShow, Class beanClass, Back<T> mBack) {
        this.context = context;
        this.isShow = isShow;
        this.beanClass = beanClass;
        this.mBack = mBack;
        mGson = new Gson();
    }

    @Override
    public void onCache(HttpInfo info) throws IOException {
        NetResultCacheTable table = null;
        try {
            table = NetResultCacheManager.getInstance().getDataByUrl(info.getUrl(), info.getParamJson());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (table != null && !StringUtils.isEmpty(table.getResponseStr())) {
            onResponse(table.getResponseStr(), 0);
        }
//        if (beanClass.getSimpleName().equals("IndexBeanResponse"))
//            onResponse(TestData.data, 0);//测试用
    }

    @Override
    public void onSuccess(HttpInfo info) throws IOException {
        String data = "";
        try {
            data = info.getRetDetail();
        } catch (Exception e) {
            e.printStackTrace();
        }
        onResponse(data, 1);
//        if (beanClass.getSimpleName().equals("SearchResultResponse"))
//            onResponse(TestData.data, 0);//测试用
    }

    @Override
    public void onFailure(HttpInfo info) throws IOException {
        int code = info.getRetCode();
        try {
            if (info.getRetCode()==HttpInfo.NonNetwork
                    || info.getRetCode()==HttpInfo.CheckNet
                    || info.getRetCode()==HttpInfo.ConnectionInterruption
                    || info.getRetCode()==HttpInfo.GatewayTimeOut
                    || info.getRetCode()==HttpInfo.GatewayBad
                    || info.getRetCode()==HttpInfo.ServerNotFound
                    || info.getRetCode()==HttpInfo.ConnectionTimeOut) {
                if (context instanceof MyActivity) {
//                    ((MyActivity) context).cancelLoadingNetError();
                    ((MyActivity) context).showToast(info.getRetMsg());
                } else if (context instanceof BaseActivity) {
//                    ((BaseActivity) context).cancelLoadingNetError();
                    ((BaseActivity) context).showToast(info.getRetMsg());
                }
                String str = info.getParamJson();
                if (!StringUtils.isEmpty(str)) {
                    ParmsBean parmsBean = new Gson().fromJson(str, ParmsBean.class);
                    String pn = parmsBean.getPn();
                    if (!StringUtils.isEmpty(pn) && pn.equals("1")) {
                        EventBus.getDefault().post(new NotNetEvent(false));
                    }
                } else {
                    EventBus.getDefault().post(new NotNetEvent(false));
                }
    //            ((MyActivity) context).showToast(info.getRetMsg());
                code = -3;
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }
        onFailure(new IOException(info.getRetMsg()), code);
    }

    private void onResponse(String data, int from) {
        LogUtils.e(beanClass.getSimpleName()+">>>onResponse:"+data);
        if (StringUtils.isEmpty(data) && from==1){
            onFailure(new IOException(context.getResources().getString(R.string.list_nothng)), -2);
            return;
        }
        try {
            if (from==1)
                LogUtils.e(">>>>xx:"+System.currentTimeMillis());
            final ResponseBase temp = mGson.fromJson(data, ResponseBase.class);
            LogUtils.e(beanClass.getSimpleName()+">>>temp.getCode():"+temp.getCode());
            if (temp.getSucc()==0 || temp.getCode()!=600) {
                if (from==1)
                    onFailure(new IOException(temp.getMsg()), temp.getCode());
            } else {
                String dataStr = temp.getData_info().toString();
                if (dataStr.equals("{}") || dataStr.equals("[]")) {
                    if (from==1 && temp.getSucc()==1 && temp.getCode()==600){
                        mBack.onResponse(null);
                        return;
                    }
                }
                ResponseBase<T> t = null;
                try {
                    t = (ResponseBase<T>) fromJsonObject(data, beanClass);
                } catch (JsonSyntaxException e) {//解析异常，说明是array数组
                    LogUtils.e(beanClass.getSimpleName()+">>>:"+e.getMessage());
                    t = (ResponseBase<T>) fromJsonArray(data, beanClass);
                }

                if (from==1)
                    LogUtils.e(">>>>yy:"+System.currentTimeMillis());
                if (from==1)
                    mBack.onResponse(t.getData_info());
                else
                    mBack.onCache(t.getData_info());
            }
        } catch (final Exception e) {
            LogUtils.e(beanClass.getSimpleName()+">>>:"+e.getMessage());
            if (from==1)
                onFailure(new IOException(context.getResources().getString(R.string.list_analysis)), -1);
        }
    }

    public void onFailure(final IOException e, int code) {
        mBack.onFailure(e, code);
        if (isShow)
            ((MyActivity)context).showToast(e.getMessage());
    }

    public <T> ResponseBase<T> fromJsonObject(String reader, Class<T> clazz) {
        Type type = new ParameterizedTypeImpl(ResponseBase.class, new Class[]{clazz});
        return new Gson().fromJson(reader, type);
    }

    public <T> ResponseBase<List<T>> fromJsonArray(String reader, Class<T> clazz) {
        // 生成List<T> 中的 List<T>
        Type listType = new ParameterizedTypeImpl(List.class, new Class[]{clazz});
        // 根据List<T>生成完整的Result<List<T>>
        Type type = new ParameterizedTypeImpl(ResponseBase.class, new Type[]{listType});
        return new Gson().fromJson(reader, type);
    }

    public static class ParameterizedTypeImpl implements ParameterizedType {
        private final Class raw;
        private final Type[] args;

        public ParameterizedTypeImpl(Class raw, Type[] args) {
            this.raw = raw;
            this.args = args != null ? args : new Type[0];
        }

        @Override
        public Type[] getActualTypeArguments() {
            return args;
        }

        @Override
        public Type getRawType() {
            return raw;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }

    public interface Back<T> {
        void onCache (T data);
        void onResponse (T data);
        void onFailure(IOException e, int code);
    }
}
